package dao

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/status"
	"prod/api/inventory"
	"prod/internal/conf"
	"prod/internal/constant"
	"prod/pkg/ecode"
	"prod/pkg/log"
	"prod/pkg/network"
	"prod/pkg/request_key"
	"strings"
	"time"
)

func newInventoryClient(ctx context.Context, inventoryAddr string) (
	client inventory.InventoryClient, err error) {
	var conn *grpc.ClientConn
	conn, err = grpc.Dial(inventoryAddr, grpc.WithInsecure(),
		grpc.WithUnaryInterceptor(network.ClientInterceptor(
			"inventory", time.Second*3, inventoryErrorTranslator)))
	if err != nil {
		err = ecode.AppendMessage(constant.ErrRemoteError, "仓库服务地址无法建立有效连接, err=%s", err.Error())
		log.FromContext(ctx).Warnw(err.Error())
		return
	}
	client = inventory.NewInventoryClient(conn)
	return
}

func inventoryErrorTranslator(err error) (errCode *ecode.ErrorCode) {
	rpcStatus := status.Convert(err)
	for _, detail := range rpcStatus.Details() {
		switch t := detail.(type) {
		case *inventory.DefaultResp:
			errCode = ecode.NewError(t.ErrorCode, t.ErrorMessage, ecode.ErrorType{
				GRPCCode: rpcStatus.Code(),
				ErrType:  t.ErrorType,
			})
			return
		}
	}
	errCode = ecode.AppendMessage(
		constant.ErrRemoteError, "仓库服务系统错误，请稍后再试")
	return
}

func (d *Dao) PreDeleteCheck(ctx context.Context, sgId uint32, ids []uint64,
	prodNameMap map[uint64]string) (err error) {
	if d.inventoryClient == nil {
		if d.inventoryClient, err = newInventoryClient(
			ctx, conf.Conf.Downstream.InventoryAddress); err != nil {
			return
		}
	}
	var resp *inventory.CheckProdDeleteReply
	clientCtx, cancel := request_key.NewOutGoingContext(ctx, time.Second*3)
	defer cancel()
	if resp, err = d.inventoryClient.PreDeleteCheck(clientCtx, &inventory.CheckProdDeleteRequest{
		SgId: sgId,
		Ids:  ids,
	}); err != nil {
		return
	}
	if len(resp.Prods) != 0 {
		errMsgs := make([]string, 0)
		prodWarehouseMap := make(map[uint64][]string)
		for _, p := range resp.Prods {
			if _, ok := prodWarehouseMap[p.Id]; !ok {
				prodWarehouseMap[p.Id] = make([]string, 0)
			}
			prodWarehouseMap[p.Id] = append(prodWarehouseMap[p.Id], p.WarehouseName)
		}
		for prodId, warehouseNames := range prodWarehouseMap {
			errMsgs = append(errMsgs, fmt.Sprintf(
				"商品%s在仓库'%s'中包含库存数量", prodNameMap[prodId],
				strings.Join(warehouseNames, ",")))
		}
		err = ecode.AppendMessage(constant.ErrForbiddenAction, strings.Join(errMsgs, ";"))
		return
	}
	return
}
